package com.sshtools.cmd.action.impl;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

import com.jcraft.jsch.Session;
import com.sshtools.cmd.action.ServerTask;
import com.sshtools.start.ConfigMgr;
import com.sshtools.utils.SSHUtils;
import com.sshtools.view.model.ServerModel;

import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import tsif.component.log.Log;
import tsif.utils.TimeUtils;

/** 同步任务 **/
public class SyncTask extends ServerTask {
	private String localPath; // 同步的文件目录
	private String remotePath; // 上传目录

	private final AtomicInteger zipCounter = new AtomicInteger(); // 压缩计数器

	// public static final boolean zipupload = Config.instance.get("zipupload",
	// false); // 是否压缩上传

	public SyncTask(ServerModel server) {
		super(server);
		// 检测有没有配置文件路径
		String filePath = server.getLocalPath();
		if (filePath != null && filePath.length() > 0) {
			this.localPath = filePath;
		} else {
			this.localPath = ConfigMgr.config.get("--syncPath", "./"); // 读取默认配置
		}
		// 给文件路径加个后缀
		if (!this.localPath.endsWith("/")) {
			this.localPath += "/";
		}

		// 获取游戏上传路径
		this.remotePath = server.getUploadPath();
		if (!this.remotePath.endsWith("/")) {
			this.remotePath += "/";
		}
	}

	@Override
	protected void execute(Session session) throws Exception {
		// 本地地址
		File socketFile = new File(localPath);
		if (!socketFile.exists()) {
			Log.error("path '" + (localPath) + "' not exists!");
			return;
		}
		if (!socketFile.isDirectory()) {
			Log.error("path '" + (localPath + "socket/") + "' isn't directory!");
			return;
		}

		// 压缩上传
		final String zipFileName = "package_" + zipCounter.incrementAndGet() + "_" + TimeUtils.toString(new Date(), "yyyymmddHHMMss") + ".zip";
		File socketZipFile = null;
		try {
			// 打包成socket.zip
			String socketZipFilePath = localPath + zipFileName;
			socketZipFile = zipDir(socketFile, socketZipFilePath);

			// 文件最后编辑日期
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Calendar cal = Calendar.getInstance();
			cal.setTimeInMillis(socketZipFile.lastModified());
			Log.info(socketZipFilePath + " " + sdf.format(cal.getTime()));

			// 上传文件夹
			Log.info("upload '" + socketZipFilePath + "' to " + remotePath);
			SSHUtils.execUpload(session, socketZipFile, remotePath);
			Log.info("finish.");
		} catch (Exception e) {
			Log.error("failure! ", e);
			// 删除本地文件
			if (socketZipFile != null && socketZipFile.exists()) {
				socketZipFile.delete();
				socketZipFile.deleteOnExit();
			}
			return;
		}
		// remote unzip socket.zip
		SSHUtils.execCmd(session, "unzip -o " + remotePath + zipFileName + " -d " + remotePath); // 执行解压压缩包
		SSHUtils.execCmd(session, "rm -f " + remotePath + zipFileName); // 删除压缩包

		// 删除本地压缩包文件
		if (socketZipFile != null && socketZipFile.exists()) {
			socketZipFile.delete();
			socketZipFile.deleteOnExit();
		}

	}

	/** 压缩文件夹 **/
	private File zipDir(File dirFile, String zipFilePath) throws ZipException {
		// 判断zip文件是否存在
		File zipSourceFile = new File(zipFilePath);
		if (zipSourceFile.exists()) {
			return zipSourceFile; // 已经存在文件
		}
		// 检测是否是文件夹
		if (!dirFile.isDirectory()) {
			return zipSourceFile;
		}
		// 创建压缩包
		Log.info("zip packing '" + zipFilePath + "'");
		ZipFile zipFile = new ZipFile(zipFilePath);

		// 遍历目录压缩
		File[] files = dirFile.listFiles();
		for (File file : files) {
			if (!file.exists()) {
				continue;
			}
			// 添加到压缩
			if (file.isDirectory()) {
				// 文件夹添加
				ZipParameters parameters = new ZipParameters();
				parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
				parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_ULTRA);
				zipFile.addFolder(file, parameters);
			} else if (file.isFile()) {
				// 文件压缩
				ZipParameters parameters = new ZipParameters();
				parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
				parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_ULTRA);
				zipFile.addFile(file, parameters);
			}
		}
		return zipSourceFile;
	}

}
